# from django.shortcuts import render
#
# # Create your views here.
# from django_redis import get_redis_connection
# from rest_framework.response import Response
# from rest_framework.status import HTTP_400_BAD_REQUEST
#
# from goods.models import SKU
# from users.utils import generic_verify_url,check_active_token
# """
# 1、先分析总体页面的需求
# ２、在分析具体的某一个小需求
#
# 需求：
#     （用户做了什么，前端传递了什么，我们后端要干什么）
#     用户在输入框中输入用户名，前端需要将用户名提交给后端，后端需要对用户名进行校验
#
# 后端的思路：
#     １、确定前端需要传递什么数据给后端
#         ①查询数据库
#         ②返回一个count
#     ２、确定请求方式　和路由
#         GET         users/usernames/itcast/
#                     users/usernames/(?P<username>\w{5,20})/count/
#         POST
#         PUT
#         DELETE
#     3、确定使用那个视图
#         APIView     :   DRF的基类  √
#         GeneriAPIView   ：   对列表视图和详情视图做了通用支持，一般和Mixin配合使用
#         ListAPIView,RetrieveAPIView     ：   连get方法都不用写，自动调用系统的Mixin实现增删改查
#     ４、按照我们的需求分析，实现步骤开发
#
#
#
# """
# # 校验用户名
#
# from users.models import User
# from rest_framework.views import APIView
# # class RegisterUsernameCountAPIView(APIView):
# #
# #     def get(self,request,username):
# #         #①查询数据库
# #         count = User.objects.filter(username=username).count()
# #         #②返回一个count
# #         data = {
# #             'count':count,
# #             'username':username,
# #         }
# #         return Response(data)
# from rest_framework.generics import GenericAPIView
# from rest_framework.mixins import CreateModelMixin
#
# class RegisterUsernameCountAPIView(GenericAPIView):
#
#     def get(self,request,username):
#
#         # books=self.get_queryset()
#
#         # ①查询数据库
#         count = User.objects.filter(username=username).count()
#         # ②返回一个count
#         data = {
#             'count':count,
#             'username':username,
#         }
#         return Response(data)
#
#
# """
# 需求：（用户做了什么，前端应该做什么，后端应该做什么）
#     需要把所有的信息都填写完成，
#     前端需要手机用户名，手机号，密码，短信验证码，确认密码和是否同意协议
#     后端完成注册
#
# 后端：
# 一、思路
#     １、接收数据
#     ２、验证数据
#     ３、数据入库
#     ４、返回响应
# 二、确定路由
#     POST    /users/
# 三、确定视图
#     3、确定使用那个视图
#         APIView     :   DRF的基类
#         GeneriAPIView   ：   对列表视图和详情视图做了通用支持，一般和Mixin配合使用
#         CreateAPIView    √ ：   连get方法都不用写，自动调用系统的Mixin实现增删改查
#     ４、按照我们的需求分析，实现步骤开发
#
# """
# from .serializers import RegisterUserSerializer,UserCenterInfoSerializer,EmailUpdateSerializer, UserHistorySerializer, SKUSerializer, AddressesCreateSerializer
#
# #  一级视图
# # class RegisterUserAPIView(APIView):
# #
# #     def post(self,request):
# #         # １、接收数据
# #         data = request.data
# #
# #         # ２、验证数据
# #         serializer = RegisterUserSerializer(data=data)
# #         serializer.is_valid()
# #
# #         # ３、数据入库,调用序列化器的save
# #         #当我们调用序列化器的save方法的时候，序列化器回调用create方法
# #         #出现了问题
# #         #instance = User.objects.create(**validated_data)
# #         #当我们的验证数据满足条件的时候
# #         #多了三个参数，需要删除
# #         user=serializer.save()
# #
# #         # 生成token
# #         from rest_framework_jwt.settings import api_settings
# #
# #         jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# #         jwt_encode_handler = api_settings.JWT_ENCODE_HANDER
# #
# #         payload = jwt_payload_handler(user)
# #         token = jwt_encode_handler(payload)
# #
# #         #将token返回回去
# #         data = serializer.data
# #         data['token']=token
# #
# #         # ４、返回响应
# #         # 将模型转化为字典，
# #         # 序列化器的实现
# #         return Response(data)
# #
#
#
# # 二级视图
# # class RegisterUserAPIView(CreateModelMixin,GenericAPIView):
# #
# #     serializer_class = RegisterUserSerializer
# #
# #     #新增数据 我们只是验证数据，将对象转化为字典
# #     #不需要查询其他的数据，所以这里不需要设置 queryset 属性
# #
# #     def post(self,request):
# #
# #         return self.create(request)
# #
# #  三级视图
# from rest_framework.generics import CreateAPIView
#
#
# class RegisterUserAPIView(CreateAPIView):
#
#     serializer_class = RegisterUserSerializer
#
# #注册完之后自动登陆
#
#
# """
# 个人中心
#
# 需求： 必须是登陆用户才可以显示个人中心，而且是 需要让前端将用户信息传递过来
#
# 后端：jwt
# 思路：①接受用户信息
#      ②根据用户信息进行查询user
#      ③将user对象转换为字典，返回
# 二、确定路由
#     GET    /users/infos
# 三、确定视图
#     3、确定使用那个视图
#         APIView     :   DRF的基类
#         GeneriAPIView   ：  √ 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
#         ListAPIView,RetrieveAPIView     ：   连get方法都不用写，自动调用系统的Mixin实现增删改查
#     ４、按照我们的需求分析，实现步骤开发
#
# """
# #一级视图
#
# # from rest_framework.mixins import RetrieveModelMixin
# from rest_framework.permissions import IsAuthenticated
# #
# # class UserCenterInfoAPIView(APIView):
# #
# #     #这个接口 只能是登陆用户才能访问
# #     #设置权限
# #     permission_classes = [IsAuthenticated]
# #
# #     def get(self,request):
# #         # ①接受用户信息
# #         user = request.user
# #
# #         # ②根据用户信息进行查询user
# #         serializer = UserCenterInfoAPIView(user)
# #
# #         # ③将user对象转换为字典，返回
# #         return Response(serializer.data)
# #三级视图
#
# from rest_framework.generics import RetrieveAPIView
# from .serializers import UserCenterInfoSerializer
#
# class UserCenterInfoAPIView(RetrieveAPIView):
#
#     permission_classes = [IsAuthenticated]
#
#     serializer_class = UserCenterInfoSerializer
#
#     #重写mixins扩展中的 get_objects方法
#     def get_object(self):
#
#         return self.request.user
#
#     # queryset = User.objects.all()
#
#
#
# """
# 邮箱的逻辑
#
# 当用户输入邮箱之后， 点击保存，这个时候，前端需要将 邮箱发送给后端
#
# 后端：
#     1、接收邮箱信息
#     2、保存邮箱到数据库中
#     3、发送一封激活邮件
#     4、用户点击激活邮件的时候，我们需要修改邮件的标记位，由未激活变为已激活
#
#
# 更新邮箱的逻辑：
#     1、让前端邮箱以及token传递给后端
#     2、后端接受数据
#     3、更新指定用户的信息
#     4、返回响应
#
# 请求的路由和方式：
#     PUT   /users/emails/   put请求的数据在请求的body中
# 确定视图
#     确定使用那个视图
#         APIView     :   DRF的基类
#         GeneriAPIView   ：   对列表视图和详情视图做了通用支持，一般和Mixin配合使用
#         UpdateAPIVIew    ： √  连put方法都不用写，自动调用系统的Mixin实现增删改查
#     按照我们的需求分析，实现步骤开发
#
#
#
# """
#
# class EmailUpdateAPIView(APIView):
#
#     permission_classes = [IsAuthenticated]
#
#     def put(self,request):
#         # 1、让前端将邮箱以及token传递给后端
#         # 2、后端接受数据
#         data = request.data
#
#         # 3、更新指定用户的信息
#         user = request.user
#
#         serializer = EmailUpdateSerializer(instance=user,data=data)
#         serializer.is_valid(raise_exception=True)
#
#         #保存
#         serializer.save()
#
#         #发送激活邮件
#         from django.core.mail import send_mail
#         # subject,   邮件标题
#         subject = '美多商城激活邮件'
#         # message,    邮件正文
#         message = ''
#         # from_email,   发件人
#         from_email = '美多商城<qi_rui_hua@163.com>'
#         # recipient_list,  收件人列表
#         email = request.data.get('email')
#         recipient_list = [email]
#
#         from users.utils import generic_verify_url
#         verify_url = generic_verify_url(request.user.id, email)
#
#         html_message = '<p>尊敬的用户您好！</p>' \
#                        '<p>感谢您使用美多商城。</p>' \
#                        '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
#                        '<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)
#
#         # send_mail(subject=subject,
#         #           message=message,
#         #           from_email=from_email,
#         #           recipient_list=recipient_list,
#         #           html_message=html_message
#         #           )
#         from celery_tasks.email.tasks import send_active_email
#
#         send_active_email.delay(subject=subject,
#                                 message=message,
#                                 from_email=from_email,
#                                 recipient_list=recipient_list,
#                                 html_message=html_message)
#
#         # 4、返回响应
#         return Response(serializer.data)
#
#
#
#
# """
# 需求：
#     当用户点击激活链接的时候，会跳转到一个激活页面，这个激活页面需要让前端将token传给后端
#
# 后端思路：
#     1、接受token
#     2、验证token
#     3、根据验证之后的数据进行查询
#     4、修改用户的激活状态
#     5、返回响应
# 确定路由方式：
#     GET     users/email/verification/?token=xxxx
#
# 确定视图
# 按照步骤开发
#
#
#
#
# """
# from rest_framework import status
# class EmailVerificationAPIView(APIView):
#
#     def get(self,request):
#         #1、接收token
#         token = request.query_params.get('token')
#         if token is None:
#
#             return Response(status=status.HTTP_400_BAD_REQUEST)
#
#         #2、验证token
#         data = check_active_token(token)
#         if data is None:
#             return Response(status=status.HTTP_400_BAD_REQUEST)
#
#         #3、根据验证之后的数据进行查询
#         user_id = data.get('user_id')
#         email = data.get('email')
#         try:
#             user = User.objects.get(id=user_id,email=email)
#         except User.DoesNotExist:
#             return Response(status=status.HTTP_400_BAD_REQUEST)
#
#         #4、修改用户的激活状态
#         user.email_active = True
#         user.save()
#
#         #5、返回响应
#         return Response({'msg':'ok'})
#
#
#
#
# """
# 地址管理
# 新增地址：
#
# 当用户将新增地址数据，填写完成之后，需要让前端手机数据
#
# 用户token，收件人，地址，电话，邮箱，省市区，发送给后端
#
# 后端：
#     1、就收数据
#     2、校验数据
#     3、数据入库
#     4、返回数据
#
# POST   users/addresses/
#
# CreatAPIView
#
# """
#
# from rest_framework.generics import CreateAPIView
#
# # class AddressesCreateAPIView(APIView):
# #
# #     permission_classes = [IsAuthenticated]
# #
# #     def post(self,request):
# #         #1、接受数据     request.data 是没有user信息的
# #         data = request.data
# #         # data['user']=request.data
# #         #2、验证数据
# #         serializer = AddressesCreateSerializer(data=data,context={'request':request})
# #         #3、数据入库
# #         serializer.is_valid(raise_exception=True)
# #         serializer.save()
# #         #4、返回响应
# #         return Response(serializer.data)
#
#
# from rest_framework import mixins
# from rest_framework.viewsets import GenericViewSet
# from .serializers import AddressSerializer
# from rest_framework.decorators import action
# from .serializers import AddressTitleSerializer
#
# class AddressViewSet(mixins.ListModelMixin,mixins.CreateModelMixin,mixins.UpdateModelMixin,GenericViewSet):
#     """
#     用户地址新增与修改
#     list GET: /users/addresses/
#     create POST: /users/addresses/
#     destroy DELETE: /users/addresses/
#     action PUT: /users/addresses/pk/status/
#     action PUT: /users/addresses/pk/title/
#
#     """
#
#     # 制定序列化器
#     serializer_class = AddressSerializer
#     # 添加用户权限
#     permission_classes = [IsAuthenticated]
#     # 由于用户的地址有存在删除的状态，所以我们需要对数据进行筛选
#     def get_queryset(self):
#         return self.request.user.addresses.filter(is_deleted=False)
#
#     def create(self, request, *args, **kwargs):
#         """
#         保存用户地址数据
#
#         """
#         count = request.user.addresses.count()
#         if count >= 20:
#             return Response({'message':'保存地址数量已经达到上限'},status=status.HTTP_400_BAD_REQUEST)
#
#         return super().create(request,*args,**kwargs)
#
#     def list(self, request, *args, **kwargs):
#         """
#         获取用户地址列表
#
#         """
#         # 获取所有地址
#         queryset = self.get_queryset()
#         # 创建序列化器
#         serializer = self.get_serializer(queryset,many=True)
#         user = self.request.user
#         # 响应
#         return Response({
#             'user_id':user.id,
#             'default_address_id':user.default_address_id,
#             'limit':20,
#             'addresses':serializer.data,
#         })
#
#     def destroy(self,request, *args, **kwargs):
#         """
#         处理删除
#
#         """
#         address = self.get_object()
#
#         # 进行逻辑删除
#         address.is_deleted = True
#         address.save()
#
#         return Response(status=status.HTTP_204_NO_CONTENT)
#
#     @action(methods=['put'],detail=True)
#     def title(self,request,pk=None,address_id=None):
#         """
#         修改标题
#
#         """
#         address = self.get_object()
#         serializer = AddressTitleSerializer(instance=address,data=request.data)
#         serializer.is_valid(raise_exception=True)
#         serializer.save()
#         return Response(serializer.data)
#
#     @action(methods=['put'],detail=True)
#     def status(self,request,pk=None,address_id=None):
#         """
#         设置默认地址
#
#         """
#         address = self.get_object()
#         request.user.default_address = address
#         request.user.save()
#         return Response({'message':'ok'},status=status.HTTP_200_OK)
#
#
#
# """
# 最近浏览
#
# 1、当 登陆用户 访问商品详情的时候，需要让前端发送一个请求，将商品id和用户信息发送给后端
#     用户信息让前端以token的形式传递过来，保存到redis中
#
#     string字符串：      key：value
#     list列表：  √        key：[value，value2，value3]
#     hash哈希：         key：field：value
#                             field2：value2
#                             field3：value3
#     set集合：          key：[value2，value1，value3]
#     zset有序集合：      key：[value1，value2，value3]
#     步骤
#         ①接受数据
#         ②验证数据
#         ③保存数据
#         ④返回响应
#     路由
#         post    users/histories/
#     视图
#         CreateAPIView
#
# 2、当用户访问个人中心的时候，需要获取当前用户的浏览记录
#     步骤
#         ①接收用户的信息
#         ②根据用户的信息查询redis中的数据
#         ③根据id查询商品的信息
#         ④将对象列表转换为字典列表
#         ⑤返回响应
#     路由
#         get
#
# """
#
# class UserHistoryAPIView(CreateAPIView):
#
#     permission_classes = [IsAuthenticated]
#
#     serializer_class = UserHistorySerializer
#
#     def get(self,request):
#         # ①接收用户的信息
#         user = request.user
#         # ②根据用户的信息查询redis中的数据
#         redis_conn = get_redis_connection('history')
#         ids = redis_conn.lrange('history_%s' % user.id,0,4)
#         # ③根据id查询商品的信息
#         skus = []
#         for sku_id in ids:
#             sku = SKU.objects.get(pk=sku_id)
#             skus.append(sku)
#         # ④将对象列表转换为字典列表
#         serializer = SKUSerializer(skus,many=True)
#         # ⑤返回响应
#         return Response(serializer.data)
#
#
# from rest_framework_jwt.views import ObtainJSONWebToken
# from cart.utils import merge_cookie_to_redis
#
#
# class UserAuthorizationView(ObtainJSONWebToken):
#
#     def post(self,request):
#         #调用jwt扩展的方法，对用户登陆的数据进行验证
#         response = super().post(request)
#
#         # 如果用户登陆成功，进行购物车数据合并
#         serializer = self.get_serializer(data=request.data)
#         if serializer.is_valid():
#             # 表示用户登陆成功
#             user = serializer.validated_data.get('user')
#             # 合并购物车
#             response = merge_cookie_to_redis(request,user,response)
#
#         return response
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
from django.shortcuts import render

# Create your views here.
from django_redis import get_redis_connection
from rest_framework.response import Response

from goods.models import SKU
from users.utils import generic_verify_url, check_active_token

"""
1. 先分析总体页面的需求
2. 再分析具体的某一个小需求


需求：
    把需求（用户做了什么，要前端传递什么，我们后端要干什么）写下来

    用户在输入框中输入了用户名，前端需要将用户名提交给后端，后端需要验证用户名是否重复

后端的思路：
    需求：
        判断用户名是否重复 可以返回给前端一个 标记（true/false）
                        也可以返回一个 count   count:0     没有注册过
                                            count：1     有注册过
    1. 确定前端需要传递什么数据给后端
        把一些简要的步骤写下来
        ① 查询数据库
        ② 返回一个count
    2. 确定请求方式 和 路由
        GET         users/usernames/itcast/
                    users/usernames/(?P<username>\w{5,20})/
                    users/usernames/(?P<username>\w{5,20})/count/
        POST
        PUT
        DELETE

    3.确定使用哪个视图
        APIView                     ：  DRF的基类
        GeneriAPIView               ： 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
        ListAPIVIew,RetrieveAPIView :  连get方法都不用写，自动调用系统的mixin实现增删改查

    4.按照我们的需求分析，实现步骤开发就可以

"""
from rest_framework.views import APIView
# from .models import User
#
# from meiduo_mall.apps.users.models import User        X 错误的导入方式
# 我们打开的是 meiduo_38 应该打开 meiduo_mall

# from apps.users.models import User  X 错误的导入方式
# 我们已经在 setting中设置过了，让 它到apps中查询子应用

from users.models import User
from rest_framework.generics import GenericAPIView
class RegisterUsernameCountAPIView(GenericAPIView):

    def get(self,request,username):

        # books = self.get_queryset()

        # ① 查询数据库
        count = User.objects.filter(username=username).count()
        # ② 返回一个count
        data = {
            'count':count,
            'username':username
        }
        return Response(data)



"""
需求： （用户做了什么，前端应该做什么，后端做什么）
    需要把所有的信息都填写完成， 前端需要收集 用户名，手机号，密码，短信验证码，确认密码和是否同意协议
    后端完成注册

后端：
    一。大体的步骤
    1.接收数据（用户名，手机号，密码，短信验证码，确认密码和是否同意协议）
    2.验证数据
    3.数据入库
    4.返回相应
    二。确定请求方式和路由

    POST    /users/

    三。确定视图
        APIView                     ：  DRF的基类
        GeneriAPIView               ： 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
        CreateAPIView                :  连post方法都不用写，自动调用系统的mixin实现增删改查
    四。按照步骤开发

"""
from .serializers import RegisterUserSerializer, UserCenterInfoSerializer, EmailUpdateSerializer, \
    AddressesCreateSerializer, UserHistroySerializer, SKUSerializer

# class RegisterUserAPIView(APIView):
#
#     def post(self,request):
#         # 1.接收数据（用户名，手机号，密码，短信验证码，确认密码和是否同意协议）
#         data = request.data
#         # 2.验证数据
#         serializer = RegisterUserSerializer(data=data)
#         serializer.is_valid()
#         # 3.数据入库
#         # 当我们调用序列化器的save方法的时候，序列化器会调用 create方法
#         # 以下代码分析出现了问题
#         # instance = User.objects.create(**validated_data)
#         # validated_data 当我们的验证数据满足条件的时候
#         # validated_data = data
#         # data = {
#         #       'usenrmae':xxx,
#         #       'password':xxx,
#         #       'password2':xxx
#         #
#         # }
#         #调用序列化器的方法
#         user=serializer.save()
#         # 4.返回相应
#         # serializer.data
#         # 在进行序列化
#         #序列化 --> 将模型转换为字典
#         # 将模型转换为字典，序列化器是如何实现的？
#         # 序列化器就是通过 自己的字段 来获取 对应的模型的属性的数据
#
#         # 生成token
#         from rest_framework_jwt.settings import api_settings
#
#         jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
#         jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
#
#         payload = jwt_payload_handler(user)
#         token = jwt_encode_handler(payload)
#
#
#         # 将token返回回去
#         data = serializer.data
#         data['token']=token
#
#         return Response(data)
#
#         # # 1.接收数据（用户名，手机号，密码，短信验证码，确认密码和是否同意协议）
#         # data = request.data
#         # username = data.get('username')
#         # password=data.get('password')
#         # password2=data.get('password2')
#         #
#         # # 2.验证数据
#         # if not all([username,password,password2]):
#         #     pass
#         #
#         # if password2 != password:
#         #     pass
#         #
#         # # 3.数据入库
#         # user = User.objects.create(**data)
#         # # 4.返回相应
#         # return Response({'username':user.username})
#
#         # 404 路由设置有问题
#         # 500 代码哪里有问题，加断点 + dubug模式
#         # 405 方法不被允许

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin

# class RegisterUserAPIView(CreateModelMixin,GenericAPIView):
#
#     serializer_class = RegisterUserSerializer
#
#     # 新增数据 我们只是验证数据，将对象转换为字典
#     # 不需要查询其他的数据，所以这里不需要设置 queryset 属性
#
#     # queryset = User.objects.all()
#
#     def post(self,request):
#
#         return self.create(request)

from rest_framework.generics import CreateAPIView
class RegisterUserAPIView(CreateAPIView):

    serializer_class = RegisterUserSerializer

# 注册完成之后自动登陆

# from users.serializers import RegisterUserSerializer
#
# from django.contrib.auth.backends import ModelBackend


"""
个人中心

需求： 必须是登陆用户才可以显示个人中心，而且是 需要让前端将用户信息传递过来的

认证方式采用的JWT
我们让前端把token传递过来
后端：
    一，大体的步骤
    1.接收用户信息
    2.根据用户信息进行查询（user）
    3.将user对象转换为字典，返回
    二，确定请求方式
    GET     /users/infos/

    三，选择视图
        APIView                     ：  DRF的基类
        GeneriAPIView               ： 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
        ListAPIView,RetrieveAPIView  :  连get方法都不用写，自动调用系统的mixin实现增删改查
    四。按照步骤开发

"""
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.permissions import IsAuthenticated
# class UserCenterInfoAPIView(APIView):
#
#     # 这个接口 只能是登陆用户才能访问
#     permission_classes = [IsAuthenticated]
#
#     def get(self,request):
#
#         #1. 接收用户信息
#         # 在这里 结合用户权限 我们就获取到了 用户信息
#         user = request.user
#         #2. 将对象转换为字典
#         serializer = UserCenterInfoSerializer(user)
#         #3. 返回数据
#         return Response(serializer.data)

from rest_framework.generics import RetrieveAPIView

class UserCenterInfoAPIView(RetrieveAPIView):


    permission_classes = [IsAuthenticated]

    serializer_class = UserCenterInfoSerializer

    # 重写 Mixin扩展中的 get_object 方法
    def get_object(self):

        return self.request.user

    # queryset = User.objects.all()

"""
邮箱的 逻辑

当用户输入邮箱之后，点击保存，这个时候，前端需要将 邮箱发送给后端

后端：
    1.接收邮箱信息
    2.保存邮箱信息到数据库中
    3.发送一封激活邮件
    4.用户点击激活邮件的时候，我们需要修改邮件的标记位 ，由未激活变为已激活

"""


"""
一，更新邮箱的逻辑是：
    1.让前端将邮箱以及token传递给后端
    2.后端接收数据
    3.更新指定用户的信息
    4.返回相应
二，请求的路由和方式
    PUT     /users/emails/          put传递的数据在 请求的body中

三，选择视图
    APIView                     ：  DRF的基类
    GeneriAPIView               ： 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
    UpdateAPIView                 :  连put方法都不用写，自动调用系统的mixin实现增删改查
四。按照步骤开发

"""
class EmailUpdateAPIView(APIView):

    permission_classes = [IsAuthenticated]

    def put(self,request):
        # 1.让前端将邮箱以及token传递给后端
        # 2.后端接收数据
        data = request.data
        # 3.更新指定用户的信息
        user = request.user

        serializer = EmailUpdateSerializer(instance=user,data=data)
        serializer.is_valid(raise_exception=True)

        serializer.save()

        # 发送激活邮件
        # ① 如何发送邮件
        # ② 发送邮件的内容

        from django.core.mail import send_mail
        #subject, message, from_email, recipient_list,
        #subject,       主题
        subject = '美多商场激活邮件'
        #  message,     信息
        message = ''
        # from_email,   发件人
        from_email = '美多商城<qi_rui_hua@163.com>'
        # recipient_list,   收件人列表
        email = request.data.get('email')
        recipient_list = [email]

        verify_url = generic_verify_url(request.user.id,email)

        html_message = '<p>尊敬的用户您好！</p>' \
                       '<p>感谢您使用美多商城。</p>' \
                       '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)

        # send_mail(subject=subject,
        #           message=message,
        #           from_email=from_email,
        #           recipient_list=recipient_list,
        #           html_message=html_message)

        from celery_tasks.email.tasks import send_active_email

        send_active_email.delay(subject=subject,
                  message=message,
                  from_email=from_email,
                  recipient_list=recipient_list,
                  html_message=html_message)

        # 4.返回相应
        return Response(serializer.data)


"""
需求：
    当用户点击激活连接的时候，会跳转到一个激活页面，这个激活页面需要让前端将token传递给后端

后端：
    一。大体步骤写下来
        1.接收token
        2.验证token
        3.根据验证之后的数据进行查询
        4.修改用户的激活状态
        5.返回相应

    二。请求方式和路由
        GET     users/email/verifications/?token=xxxx

    三。确定视图

    四。按照步骤开发

"""
from rest_framework import status
class EmailVerificationAPIView(APIView):

    def get(self,request):
        # 1.接收token
        token = request.query_params.get('token')
        if token is None:

            return Response(status=status.HTTP_400_BAD_REQUEST)
        # 2.验证token
        data = check_active_token(token)
        if data is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        # 3.根据验证之后的数据进行查询
        user_id = data.get('user_id')
        email=data.get('email')
        # and
        # filter().filter()
        # filter(,,,,)
        try:
            user = User.objects.get(id=user_id,email=email)
        except User.DoesNotExist:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        # 4.修改用户的激活状态
        user.email_active=True
        user.save()
        # 5.返回相应
        return Response({'msg':'ok'})


"""
地址管理
新增地址：

当用户将新增地址数据，填写完成之后，需要让前端收集数据
我们可以让前端将 用户id传递过来，但是我们讲的时候，让前端将token传递过来

用户token，收件人，地址，电话，省，市，区，固定电话，邮箱发送给后端

后端：
    1.接收数据
    2.验证数据
    3.数据入库
    4.返回相应

    POST    /users/addresses/

    CreateAPIView
"""
from rest_framework.generics import CreateAPIView
# class AddressesCreateAPIView(CreateAPIView):

    # serializer_class =
    # pass


# class AddressesCreateAPIView(APIView):
#
#     permission_classes = [IsAuthenticated]
#
#     def post(self,request):
#         # request.user
#
#         # 1.接收数据
#         # request.data 是没有 user信息的
#         data = request.data
#         # data['user']=request.user
#
#         # 2.验证数据
#         serializer = AddressesCreateSerializer(data=data,context={'request':request})
#         # 3.数据入库
#         serializer.is_valid(raise_exception=True)
#         serializer.save()
#         # 4.返回相应
#         return Response(serializer.data)

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from .serializers import AddressSerializer
from rest_framework.decorators import action
from .serializers import AddressTitleSerializer

class AddressViewSet(mixins.ListModelMixin,mixins.CreateModelMixin,mixins.UpdateModelMixin,GenericViewSet):
    """
    用户地址新增与修改
    list GET: /users/addresses/
    create POST: /users/addresses/
    destroy DELETE: /users/addresses/
    action PUT: /users/addresses/pk/status/
    action PUT: /users/addresses/pk/title/
    """

    #制定序列化器
    serializer_class = AddressSerializer
    #添加用户权限
    permission_classes = [IsAuthenticated]
    #由于用户的地址有存在删除的状态,所以我们需要对数据进行筛选
    def get_queryset(self):
        return self.request.user.addresses.filter(is_deleted=False)

    def create(self, request, *args, **kwargs):
        """
        保存用户地址数据
        """
        count = request.user.addresses.count()
        if count >= 20:
            return Response({'message':'保存地址数量已经达到上限'},status=status.HTTP_400_BAD_REQUEST)

        return super().create(request,*args,**kwargs)

    def list(self, request, *args, **kwargs):
        """
        获取用户地址列表
        """
        # 获取所有地址
        queryset = self.get_queryset()
        # 创建序列化器
        serializer = self.get_serializer(queryset, many=True)
        user = self.request.user
        # 响应
        return Response({
            'user_id': user.id,
            'default_address_id': user.default_address_id,
            'limit': 20,
            'addresses': serializer.data,
        })

    def destroy(self, request, *args, **kwargs):
        """
        处理删除
        """
        address = self.get_object()

        # 进行逻辑删除
        address.is_deleted = True
        address.save()

        return Response(status=status.HTTP_204_NO_CONTENT)



    @action(methods=['put'], detail=True)
    def title(self, request, pk=None, address_id=None):
        """
        修改标题
        """
        address = self.get_object()
        serializer = AddressTitleSerializer(instance=address, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    @action(methods=['put'], detail=True)
    def status(self, request, pk=None, address_id=None):
        """
        设置默认地址
        """
        address = self.get_object()
        request.user.default_address = address
        request.user.save()
        return Response({'message': 'OK'}, status=status.HTTP_200_OK)


"""
最近浏览

1. 当登陆用户访问商品详情的时候，需要让前端发送一个请求，将商品id和用户信息发送给后端

2. 当登陆用户访问个人中心的时候，需要获取当前用户的浏览记录




1. 当登陆用户访问商品详情的时候，需要让前端发送一个请求，将商品id和用户信息发送给后端
    用户信息让前端以 token的形式传递过来

    sku_id,user_id
    保存在 redis中

    1: [2,3,4,5,6]

    Redis


    String 字符串:     key:value

    List 列表:        key: [value1,value2,value2]     1:[2,3,4,5]

    Hash 哈希:        key:  field:value
                            field2:value2
                            field3:value3

    Set 集合:         key: [value2,value1,value3]

    ZSet 有序集合:     key: [value1,value2,value3]     1:[2,3,4,5]

后端
    接口只能是登陆用户访问
    大体步骤：
        接收数据
        验证数据
        把数据保存起来
        返回相应
    请求方式和路由
        POST    users/histories/

    确定视图
      APIView                     ：  DRF的基类
      GeneriAPIView               ： 对列表视图和详情视图做了通用支持，一般和Mixin配合使用
      CreateAPIView                 :  连post方法都不用写，自动调用系统的mixin实现增删改查

    按照步骤开发


2. 当登陆用户访问个人中心的时候，需要获取当前用户的浏览记录
    用户信息让前端以 token的形式传递过来

    后端：
        大体步骤：
            接收用户的信息
            根据用户的信息查询redis中的数据  [1,2,,3]
            根据id查询商品的信息             [sku，sku,sku]
            将对象列表转换为字典列表
            返回相应
        请求方式和路由
            GET


"""

class UserHistoryAPIView(CreateAPIView):

    permission_classes = [IsAuthenticated]

    serializer_class = UserHistroySerializer


    def get(self,request):
        # 接收用户的信息
        user = request.user
        # 根据用户的信息查询redis中的数据  [1,2,,3]
        redis_conn = get_redis_connection('history')
        ids = redis_conn.lrange('history_%s'%user.id,0,4)
        # 根据id查询商品的信息             [sku，sku,sku]
        # skus = SKU.objects.filter(pk__in=ids)
        # SKU.objects.filter(pk__in=ids) 原有的顺序就不存在了

        skus = []

        for sku_id in ids:
            sku = SKU.objects.get(pk=sku_id)
            skus.append(sku)



        # 将对象列表转换为字典列表
        serializer = SKUSerializer(skus,many=True)
        # 返回相应
        return Response(serializer.data)


from rest_framework_jwt.views import ObtainJSONWebToken
from cart.utils import merge_cookie_to_redis

class UserAuthorizationView(ObtainJSONWebToken):

    def post(self, request):
        # 调用jwt扩展的方法，对用户登录的数据进行验证
        response = super().post(request)

        # # 如果用户登录成功，进行购物车数据合并
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            # 表示用户登录成功
            user = serializer.validated_data.get("user")
            # 合并购物车
            #merge_cart_cookie_to_redis(request, user, response)
            response = merge_cookie_to_redis(request, user, response)

        return response